/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.antlr;
import antlr.*;
import org.openide.nodes.*;
/**
* <b>SOFTWARE RIGHTS</b>
* <p>
* ANTLR 2.6.0 MageLang Institute
* <p>
* We reserve no legal rights to the ANTLR--it is fully in the
* public domain. An individual or company may do whatever
* they wish with source code distributed with ANTLR or the
* code generated by ANTLR, including the incorporation of
* ANTLR, or its output, into commerical software.
* <p>
* We encourage users to develop software with ANTLR. However,
* we do ask that credit is given to us for developing
* ANTLR. By "credit", we mean that if you use ANTLR or
* incorporate any source code into one of your programs
* (commercial product, research project, or otherwise) that
* you acknowledge this fact somewhere in the documentation,
* research report, etc... If you like ANTLR and have
* developed a nice tool with the output, please mention that
* you developed it using ANTLR. In addition, we ask that the
* headers remain intact in our source code. As long as these
* guidelines are kept, we expect to continue enhancing this
* system and expect to make other tools available as they are
* completed.
* <p>
* The ANTLR gang:
* @version ANTLR 2.6.0 MageLang Institute
* @author Terence Parr, <a href=http://www.MageLang.com>MageLang Institute</a>
* @author <br>John Lilley, <a href=http://www.Empathy.com>Empathy Software</a>
*/
import java.io.*;
import antlr.collections.impl.BitSet;
import antlr.collections.impl.Vector;
public class Tool extends antlr.Tool {
public static final String version = "2.6.0";
// Object that handles analysis errors
ToolErrorHandler errorHandler;
// Was there an error during parsing or analysis?
protected boolean hasError = false;
// Generate diagnostics? (vs code)
boolean genDiagnostics = false;
/** Generate HTML vs code? */
boolean genHTML = false;
/** Current output directory for generated files */
protected static String outputDir = ".";
// Grammar input
String grammarFile;
transient Reader f = new InputStreamReader(System.in);
// SAS: changed for proper text io
// transient DataInputStream in = null;
protected static String literalsPrefix = "LITERAL_";
protected static boolean upperCaseMangledLiterals = false;
private static BitSet cmdLineArgValid = new BitSet();
/** Construct a new Tool. */
public Tool() {
// SAS: removed private so could create subclass
errorHandler = new antlr.DefaultToolErrorHandler();
}
private static void checkForInvalidArguments(String[] args, BitSet cmdLineArgValid) {
// check for invalid command line args
for (int a = 0; a < args.length; a++) {
if (!cmdLineArgValid.member(a)) {
warning("invalid command-line argument: " + args[a] + "; ignored");
}
}
}
/** Perform processing on the grammar file. Can only be called from main()
* @param args The command-line arguments passed to main()
*/
protected void doEverything(String[] args) {
// SAS: removed "private" so subclass can call
// (The subclass is for the VAJ interface)
// run the preprocessor to handle inheritance first.
antlr.preprocessor.Tool preTool = new antlr.preprocessor.Tool(this, args);
if ( !preTool.preprocess() ) {
inform("Preprocessor failed!");
return;
}
String[] modifiedArgs = preTool.preprocessedArgList();
// process arguments for the Tool
processArguments(modifiedArgs);
try {
if (grammarFile != null) {
f = new FileReader(grammarFile);
}
}
catch (IOException e) {
inform("Error: cannot open grammar file " + grammarFile);
help();
return;
}
TokenBuffer tokenBuf = new TokenBuffer(new ANTLRLexer(f));
LLkAnalyzer analyzer = new LLkAnalyzer(this);
MakeGrammar behavior = new MakeGrammar(this, args, analyzer);
try {
ANTLRParser p = new ANTLRParser(tokenBuf, behavior, this);
p.setFilename(grammarFile);
p.grammar();
if (hasError) {
inform("Exiting due to errors.");
return;
}
checkForInvalidArguments(modifiedArgs, cmdLineArgValid);
// Create the right code generator according to the "language" option
CodeGenerator codeGen;
// SAS: created getLanguage() method so subclass can override
// (necessary for VAJ interface)
String codeGenClassName = "antlr." + getLanguage(behavior) + "CodeGenerator";
try {
Class codeGenClass = Class.forName(codeGenClassName);
codeGen = (CodeGenerator)codeGenClass.newInstance();
codeGen.setBehavior(behavior);
codeGen.setAnalyzer(analyzer);
codeGen.setTool(this);
codeGen.gen();
}
catch (ClassNotFoundException cnfe) {
panic("Cannot instantiate code-generator: " + codeGenClassName);
}
catch (InstantiationException ie) {
panic("Cannot instantiate code-generator: " + codeGenClassName);
}
catch (IllegalArgumentException ie) {
panic("Cannot instantiate code-generator: " + codeGenClassName);
}
catch (IllegalAccessException iae) {
panic("code-generator class '" + codeGenClassName + "' is not accessible");
}
}
catch (MismatchedTokenException mt) {
inform("Unhandled parser error: " + mt.getMessage());
}
catch (NoViableAltException nva) {
inform("Unhandled parser error: " + nva.getMessage());
}
catch (ParserException pe) {
inform("Unhandled parser error: " + pe.getMessage());
}
catch (IOException io) {
inform("IOException: " + io.getMessage());
}
}
/** Issue an error
* @param s The message
*/
public void error(String s) {
hasError = true;
inform("error: "+s);
}
/** Issue an error with line number information
* @param s The message
* @param file The file that has the error
* @param line The grammar file line number on which the error occured
*/
public void error(String s, String file, int line) {
hasError = true;
if ( file!=null ) {
inform("error in "+file+": line("+line+"), "+s);
}
else {
inform("error; line "+line+": "+s);
}
}
public static Object factory(String p) {
Class c;
Object o=null;
try {
c = Class.forName(p);// get class def
o = c.newInstance(); // make a new one
}
catch (Exception e) {
// either class not found,
// class is interface/abstract, or
// class or initializer is not accessible.
warning("Can't create an object of type " + p);
return null;
}
return o;
}
/** Determine the language used for this run of ANTLR
* This was made a method so the subclass can override it
*/
public String getLanguage(MakeGrammar behavior) {
if (genDiagnostics) {
return "Diagnostic";
}
if (genHTML) {
return "HTML";
}
return behavior.language; // "Java"
}
public static String getOutputDirectory() { return outputDir; }
static private void help() {
inform("HELP for ANTLR");
}
public static void main(String[] args) {
setRootNode("ANTLR Parser Generator Version "+
Tool.version+" 1989-1999 MageLang Institute");
org.openide.TopManager.getDefault().getNodeOperation().explore(rootNode);
args = new String[] { "-o", "z:\\p\\antlr\\tst\\", "z:\\p\\antlr\\tst\\calc.g" };
try {
if ( args.length==0 ) {
help();
}
Tool theTool = new Tool();
theTool.doEverything(args);
theTool = null;
}
catch (Exception e) {
System.err.println(System.getProperty("line.separator")+
System.getProperty("line.separator"));
System.err.println("#$%%*&@# internal error: "+e.toString());
System.err.println("[complain to nearest government official");
System.err.println(" or send hate-mail to parrt@jguru.com;");
System.err.println(" please send stack trace with report.]"+
System.getProperty("line.separator"));
e.printStackTrace();
}
inform("ANTLR NetBeans module done compilation!!");
}
public static PrintWriter openOutputFile(String f) throws IOException {
return new PrintWriter(new FileWriter(outputDir+System.getProperty("file.separator")+f));
}
/** Issue an unknown fatal error */
public static void panic() {
inform("panic");
return;//System.exit(1);
}
/** Issue a fatal error message
* @param s The message
*/
public static void panic(String s) {
inform("panic: "+s);
return;//System.exit(1);
}
/** Process the command-line arguments. Can only be called by Tool.
* @param args The command-line arguments passed to main()
*/
private void processArguments(String[] args) {
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-diagnostic")) {
genDiagnostics = true;
genHTML = false;
Tool.setArgOK(i);
} else {
if (args[i].equals("-o")) {
Tool.setArgOK(i);
if (i + 1 >= args.length) {
error("missing output directory with -o option; ignoring");
} else {
i++;
setOutputDirectory(args[i]);
Tool.setArgOK(i);
}
} else
if (args[i].equals("-html")) {
genHTML = true;
genDiagnostics = false;
Tool.setArgOK(i);
} else {
if (args[i].charAt(0) != '-') {
// Must be the grammar file
grammarFile = args[i];
Tool.setArgOK(i);
}
}
}
}
}
public static void setArgOK(int i) {
cmdLineArgValid.add(i);
}
public static void setOutputDirectory(String o) { outputDir = o; }
static Node rootNode = null;
static void setRootNode(String s) {
rootNode = new AbstractNode(new Children.Array());
rootNode.setDisplayName(s);
}
static void inform(String s) {
Node n = new AbstractNode(Children.LEAF);
n.setDisplayName(s);
rootNode.getChildren().add(new Node[]{ n });
}
/** Issue an error; used for general tool errors not for grammar stuff
* @param s The message
*/
public static void toolError(String s) {
inform("error: "+s);
}
/** Issue a warning
* @param s the message
*/
public static void warning(String s) {
inform("warning: "+s);
}
/** Issue a warning with line number information
* @param s The message
* @param file The file that has the warning
* @param line The grammar file line number on which the warning occured
*/
public static void warning(String s, String file, int line) {
if ( file!=null ) {
inform("warning in "+file+": line("+line+"), "+s);
}
else {
inform("warning; line "+line+": "+s);
}
}
}